package com.luis.controller;

import com.luis.model.CreditorInfo;
import com.luis.service.CreditorInfoServer;
import com.luis.utils.FastDFSUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;

/**
 * @Author: Luis
 * @date: 2022/4/12 15:49
 * @description:
 */
@Controller
public class CreditorInfoController {

    @Resource
    private CreditorInfoServer creditorInfoServer;

    @RequestMapping("/")
    public String creditors(Model model) {
        List<CreditorInfo> creditorInfoList = creditorInfoServer.queryAll();
        model.addAttribute("creditorInfoList", creditorInfoList);
        return "creditors";
    }

    @GetMapping("/upload/{id}")
    public String toUpload(@PathVariable Integer id, Model model) {
        CreditorInfo creditorInfo = creditorInfoServer.findById(id);
        model.addAttribute("creditorInfo", creditorInfo);
        return "upload";
    }

    /**
     * 文件上传
     *      参数MultipartFile：为Spring提供的一个类，专门用于封装请求中的文件数据，
     *      其属性名必须与表单中文件域的名字完全相同！否则无法获取文件数据！
     */
    @PostMapping("/upload")
    public String upload(Integer id, MultipartFile myFile, Model model) throws IOException {
        // System.out.println(myFile.getBytes()); // 获取文件对应字节数组
        // System.out.println(myFile.getContentType()); // 获取文件类型
        // System.out.println(myFile.getInputStream()); // 获取文件对应的输入流
        // System.out.println(myFile.getName()); // 获取表单元素名
        // System.out.println(myFile.getOriginalFilename()); // 获取文件名
        // System.out.println(myFile.getSize()); // 获取文件大小
        // System.out.println(myFile.isEmpty()); //判断文件是否为空；文件没有上传或文件大小为0，这个值都是true

        // 获取上传文件对应的字节数组
        byte[] fileBuff = myFile.getBytes();
        // 获取上传文件的文件名
        String fileName = myFile.getOriginalFilename();
        // 获取上传文件的扩展名
        // #TODO 可能会出现问题，因为有的文件有可能没有扩展名，所以必要时需要做逻辑控制
        String fileExtName = fileName.substring(fileName.lastIndexOf(".") + 1);
        Long fileSize = myFile.getSize(); // 文件大小
        String fileType = myFile.getContentType(); // 文件类型

        // ================进行文件上传========上传到FastDFS文件系统中=============
        String[] result = FastDFSUtil.upload(fileBuff, fileExtName);

        CreditorInfo creditorInfo = new CreditorInfo();
        creditorInfo.setId(id); // id
        creditorInfo.setGroupName(result[0]); // 组名
        creditorInfo.setRemoteFilePath(result[1]); // 远程文件地址
        creditorInfo.setOldFileName(fileName); // 文件名
        creditorInfo.setFileSize(fileSize); // 文件大小
        creditorInfo.setFileType(fileType); // 文件类型

        // ==========更新数据库信息==========
        creditorInfoServer.updateFileInfo(creditorInfo);
        model.addAttribute("msg", "上传成功，是否返回列表页面？");
        model.addAttribute("url", "/");
        return "success";
    }

    /**
     * 文件下载
     * @param id 需要下载的文件主键
     * @return ResponseEntity 表示一个响应的实体，这个类是Spring提供的一个类，是Spring响应数据时的一个对象，
     *          这个对象有包含着响应时的编码如404 202 等，以及响应的头文件信息，以及响应时的具体数据；
     *          这个对象可以是一段html代码，也可是是一段JS，也可以是一段普通字符串，也可以是一个文件的流
     */
    @RequestMapping("/download/{id}")
    public ResponseEntity<byte[]> download(@PathVariable Integer id) {

        // 获取响应数据（即下载后成功返回的字节数组）
        CreditorInfo info = creditorInfoServer.findById(id);
        String groupName = info.getGroupName();
        String remoteFilePath = info.getRemoteFilePath();
        byte[] buffFile = FastDFSUtil.download(groupName, remoteFilePath);

        // 设置响应时的头文件信息
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 设置响应类型为文件类型
        headers.setContentLength(info.getFileSize()); // 设置响应时的文件大小，用于提供下载进度显示使用

        // 设置下载时的默认文件名
        headers.setContentDispositionFormData("attachment", info.getOldFileName());
        /**
         * 创建响应实体对象，Spring会将这个对象返回给浏览器，作为响应数据；（我们需要填充数据）
         *      参数1：响应时的具体数据
         *      参数2：响应时的头文件信息
         *      参数3：响应时的状态码
         */
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(buffFile, headers, HttpStatus.OK);
        return responseEntity;
    }

    /**
     * 文件删除
     *      文件删除操作选择在业务层进行，因为需要先查数据，才能进行删除，减少方法调用。
     * @param id
     * @return
     */
    @RequestMapping("/delete/{id}")
    public String delete(@PathVariable Integer id) {
        creditorInfoServer.deleteFileById(id);
        return "redirect:/";
    }
}
